package connection

import (
	"context"
	"errors"
	"fmt"
	"log"
	"net"
	"sync"
	"zinxtcp/default/connevent"
	"zinxtcp/default/encoder"
	"zinxtcp/utils"
	"zinxtcp/ziface"
)

/*
   连接管理模块
*/
type ConnManager struct {
	ctx         context.Context
	cancelFunc  context.CancelFunc
	stopListen  chan bool
	connCount   uint32
	connPool    chan bool
	connections map[uint32]ziface.IConnection //管理的连接信息
	connLock    sync.RWMutex                  //读写连接的读写锁
	encoder     ziface.IEncoder               //解码器
	connEvent   ziface.IConnEvent             //时间处理器
}

/*
   创建一个链接管理
*/
func NewConnManager() *ConnManager {
	c, cf := context.WithCancel(context.Background())
	return &ConnManager{
		ctx:         c,
		cancelFunc:  cf,
		stopListen:  make(chan bool),
		connCount:   utils.GlobalObject.MaxConn,
		connPool:    make(chan bool, utils.GlobalObject.MaxConn),
		connections: make(map[uint32]ziface.IConnection),
	}
}

func (connMgr *ConnManager) Listening(listener *net.TCPListener) {
	for i := 0; i < int(connMgr.connCount); i++ {
		connMgr.connPool <- true
	}
	var cid uint32
	cid = 1
	for {
		select {
		case <-connMgr.stopListen:
			log.Println("Conn Manager stop to accept new connection")
			return
		case <-connMgr.connPool:
			c, err := listener.AcceptTCP()
			if err != nil {
				log.Println("Accept 失败: " + err.Error())
			} else {
				conn := NewConnection(connMgr.ctx, c, cid, connMgr)
				go conn.Start()
				connMgr.Add(conn)
				cid++
			}
		}
	}
}

//添加链接
func (connMgr *ConnManager) Add(conn ziface.IConnection) {
	//保护共享资源Map 加写锁
	connMgr.connLock.Lock()
	//将conn连接添加到ConnMananger中
	connMgr.connections[conn.GetConnID()] = conn
	connMgr.connLock.Unlock()

	fmt.Println("connection add to ConnManager successfully: conn num = ", connMgr.Len())
}

//删除连接
func (connMgr *ConnManager) Remove(conn ziface.IConnection) {
	if _, ok := connMgr.connections[conn.GetConnID()]; !ok {
		return
	}
	//保护共享资源Map 加写锁
	connMgr.connLock.Lock()
	defer connMgr.connLock.Unlock()

	//删除连接信息
	delete(connMgr.connections, conn.GetConnID())
	if connMgr.connPool != nil {
		connMgr.connPool <- true
	}
	fmt.Println("connection Remove ConnID=", conn.GetConnID(), " successfully: conn num = ", connMgr.Len())
}

//删除连接
func (connMgr *ConnManager) RemoveById(connID uint32) {
	if connID == 0 {
		panic("ConnManager RemoveById func ConnID is  Zero")
	}
	//保护共享资源Map 加写锁
	connMgr.connLock.Lock()
	delete(connMgr.connections, connID)
	connMgr.connLock.Unlock()

	if connMgr.connPool != nil {
		connMgr.connPool <- true
	}
	fmt.Println("connection RemoveById ConnID=", connID, " successfully: conn num = ", connMgr.Len())
}

//利用ConnID获取链接
func (connMgr *ConnManager) Get(connID uint32) (ziface.IConnection, error) {
	//保护共享资源Map 加读锁
	connMgr.connLock.RLock()
	conn, ok := connMgr.connections[connID]
	connMgr.connLock.RUnlock()
	if ok {
		return conn, nil
	} else {
		return nil, errors.New("connection not found")
	}
}

//获取当前连接
func (connMgr *ConnManager) Len() int {
	return len(connMgr.connections)
}

//清除并停止所有连接
func (connMgr *ConnManager) ClearConn() {
	fmt.Println("Begin to Clear All Connections.")
	//保护共享资源Map 加写锁
	connMgr.connLock.Lock()
	defer connMgr.connLock.Unlock()

	//停止并删除全部的连接信息
	for connID, conn := range connMgr.connections {
		//删除
		delete(connMgr.connections, connID)
		//停止
		conn.Stop()
	}

	fmt.Println("Clear All Connections successfully: conn num = ", connMgr.Len())
}

func (connMgr *ConnManager) Stop() {
	connMgr.stopListen <- true
	connPool := connMgr.connPool
	connMgr.connPool = nil
	close(connPool)
	connMgr.cancelFunc()
	for connID, conn := range connMgr.connections {
		fmt.Printf("the Connections on ClearConn func with id: %d. ", connID)
		fmt.Printf("the Connections on ClearConn func with conn : %+v. ", conn)
		fmt.Printf("---> shuts down the reading side of the TCP connection of connID: %d....\n", connID)
		//停止
		conn.GetTCPConnection().CloseRead()
	}
}

func (connMgr *ConnManager) SetEncoder(enc ziface.IEncoder) {
	connMgr.encoder = enc
}

func (connMgr *ConnManager) GetEncoder() ziface.IEncoder {
	if connMgr.encoder == nil {
		connMgr.encoder = &encoder.Encoder{}
	}
	return connMgr.encoder
}

//设置事件处理器
func (connMgr *ConnManager) SetConnEvent(ce ziface.IConnEvent) {
	connMgr.connEvent = ce
}

//设置事件处理器
func (connMgr *ConnManager) GetConnEvent() ziface.IConnEvent {
	if connMgr.connEvent == nil {
		connMgr.connEvent = &connevent.ConnEvent{}
	}
	return connMgr.connEvent
}
